package com.android.action;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import org.apache.http.util.TextUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ViewInject extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        Project project = e.getProject();
        Editor editor = e.getData(CommonDataKeys.EDITOR);
        Document document = editor.getDocument();

        //光标位置写入
        CaretModel caretModel = editor.getCaretModel();

        //获取选中文字
        SelectionModel selectionMode = editor.getSelectionModel();
        String selectText = selectionMode.getSelectedText();
        if (TextUtils.isEmpty(selectText)) {
            Messages.showMessageDialog("Select the layout name, such as: R.layout. Aty_main, and select aty_main", "提示", Messages.getInformationIcon());
            return;
        }

        //当前文件
        PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
        String currentContent = psiFile.getViewProvider().getContents().toString();
        String current[] = currentContent.split("\n");

        StringBuffer packageSb = new StringBuffer();
        packageSb.append("import android.widget.*;");
        packageSb.append("\n");
        packageSb.append("import com.android.annotation.ViewInject;");
        packageSb.append("\n");

        StringBuffer sbPackage = new StringBuffer();
        for (int i = 0; i < current.length; i++) {
            if (current[i].contains("import")) {
                break;
            } else {
                sbPackage.append(current[i] + "\n");
            }
        }

        WriteCommandAction.runWriteCommandAction(project, new Runnable() {
            @Override
            public void run() {
                document.insertString(sbPackage.length(), packageSb.toString());
            }
        });

        List<Map<String, String>> list = findViewIdByXmlName(project, selectText);

        StringBuffer fieldSb = new StringBuffer("\n");
        for (int i = 0; i < list.size(); i++) {
            Map<String, String> map = list.get(i);
            String id = map.get("id");
            String name = map.get("name");

            fieldSb.append("    @ViewInject(R.id." + id + ")");
            fieldSb.append("\n");
            fieldSb.append("    private " + name + " " + id + ";");
            fieldSb.append("\n");
        }

        StringBuffer sbTop = new StringBuffer();
        for (int i = 0; i < current.length; i++) {
            sbTop.append(current[i] + "\n");
            if (current[i].contains("{")) {
                break;
            }
        }

        WriteCommandAction.runWriteCommandAction(project, new Runnable() {
            @Override
            public void run() {
                document.insertString(sbTop.length() + packageSb.toString().length(), fieldSb.toString());
            }
        });

    }

    @Override
    public void update(AnActionEvent e) {
        super.update(e);
        //Get required data keys
        final Project project = e.getProject();
        final Editor editor = e.getData(CommonDataKeys.EDITOR);
        //Set visibility only in case of existing project and editor and if some text in the editor is selected
        e.getPresentation().setEnabled(project != null && editor != null);
    }

    protected PsiClass getTargetClass(Editor editor, PsiFile file) {
        int offset = editor.getCaretModel().getOffset();
        PsiElement element = file.findElementAt(offset);
        if (element == null) {
            return null;
        } else {
            PsiClass target = (PsiClass) PsiTreeUtil.getParentOfType(element, PsiClass.class);
            return target instanceof SyntheticElement ? null : target;
        }
    }

    /**
     * 全局搜索xml文件
     *
     * @param project 项目
     * @param xmlName xml名字
     * @return
     */
    private List<Map<String, String>> findViewIdByXmlName(Project project, String xmlName) {
        List<Map<String, String>> idList = new ArrayList<>();
        PsiFileSystemItem[] items = FilenameIndex.getFilesByName(project, xmlName + ".xml", GlobalSearchScope.allScope(project), false);
        if (items.length == 1) {
            XmlFile xmlFile = (XmlFile) PsiManager.getInstance(project).findFile(items[0].getVirtualFile());
            XmlTag tag = xmlFile.getRootTag();
            findViewByXmlTag(project, tag, idList);
        }
        return idList;
    }

    private List<Map<String, String>> findViewByXmlTag(Project project, XmlTag tag, List<Map<String, String>> idList) {
        putMap(project, tag, idList);
        XmlTag[] xmlTags = tag.getSubTags();
        for (int i = 0; i < xmlTags.length; i++) {
            XmlTag xmlTag = xmlTags[i];
            putMap(project, xmlTag, idList);
            XmlTag[] subTags = xmlTag.getSubTags();
            if (subTags.length != 0) {
                for (int j = 0; j < subTags.length; j++) {
                    findViewByXmlTag(project, subTags[j], idList);
                }
            }
        }
        return idList;
    }

    private void putMap(Project project, XmlTag xmlTag, List<Map<String, String>> idList) {
        if (xmlTag.getAttributeValue("android:id") != null) {
            Map<String, String> map = new HashMap<>();
            map.put("name", xmlTag.getName());
            map.put("id", xmlTag.getAttributeValue("android:id").replace("@+id/", ""));
            idList.add(map);
        }
        if (xmlTag.getName().equals("include") && xmlTag.getAttributeValue("layout") != null) {
            String name = xmlTag.getAttributeValue("layout").replace("@layout/", "");
            idList.addAll(findViewIdByXmlName(project, name));
        }
    }


}
